package parser;

import com.github.javaparser.ParseException;
import com.github.javaparser.ast.type.TypeParameter;
import com.thoughtworks.qdox.model.JavaField;
import com.thoughtworks.qdox.model.JavaType;
import entity.ClassEntity;
import entity.FieldEntity;
import entity.VariableEntity;
import type.AccessModifierEnum;
import type.ContainerTypeEnum;
import type.VariableTypeEnum;

import java.io.IOException;

public class FieldParser {
    public static FieldEntity createFieldEntity(JavaField jf) throws IOException, ParseException {
        FieldEntity entity = null;
        if (jf != null) {
            entity = new FieldEntity();
            // 成员变量名
            entity.setName(jf.getName());
            // 代码 【类型+全限定变量名】java.io.File file
            entity.setCode(jf.getType().getFullyQualifiedName() + " " + jf.getName());
            // 访问修饰符
            entity.setAccessModifierEnum(getAccessModifier(jf));
            // 一般修饰符
            entity.setStatic(jf.isStatic());
            entity.setStrictfp(jf.isStrictfp());
            entity.setTransient(jf.isTransient());
            entity.setVolatile(jf.isVolatile());
            entity.setFinal(jf.isFinal());
            // 成员变量所在的类
            entity.setDeclarationClass(jf.getDeclaringClass());
            // 成员变量分类 基本数据类型 or 一般引用类型 or 泛型
            entity.setVariableTypeEnum(getVariableType(jf));
            // 变量具体类型 类全限定名 or 泛型声明 or 基本数据类型
            entity.setOriginClass(getOriginClass(entity.getVariableTypeEnum(), jf));
            // 是容器？
            entity.setContainerType(getContainerType(jf, entity.getVariableTypeEnum()));
            // 容器元素
            entity.setContainerItems(getContainerItems(jf, entity.getContainerType()));
        }
        return entity;
    }

    /**
     * 提取容器元素类型
     */
    public static VariableEntity[] getContainerItems(JavaField jf, ContainerTypeEnum type) throws IOException, ParseException {
        VariableEntity[] containerItems = new VariableEntity[2];
        if (type == ContainerTypeEnum.ARRAY) {
            containerItems[0] = VariableParser.createVariableEntity(jf.getType().getComponentType());
            return containerItems;
        }
        if (type == ContainerTypeEnum.COLLECTION || type == ContainerTypeEnum.CUSTOM) {
            String str = jf.getType().getGenericFullyQualifiedName();
            containerItems[0] = VariableParser.createVariableEntity(str.substring(str.indexOf('<') + 1, str.lastIndexOf('>')));
            return containerItems;
        }
        if (type == ContainerTypeEnum.MAP) {
            String str = jf.getType().getGenericFullyQualifiedName();
            str = str.substring(str.indexOf('<') + 1, str.lastIndexOf('>'));
            String[] tmp = str.split(",");
            containerItems[0] = VariableParser.createVariableEntity(tmp[0]);
            containerItems[1] = VariableParser.createVariableEntity(tmp[1]);
            return containerItems;
        }
        return null;
    }

    /**
     * 判断是容器
     * 容器（可存储相同类型元素）包括：
     * 1. 单列集合：实现 java.util.Collection 接口
     * 2. 双列集合：实现 java.util.Map 接口
     * 3. 自定义容器：实现 java.util.Iterator 或 java.util.Enumeration 接口
     * 4. 数组
     * 3 的例子：NetworkInterface.getNetworkInterfaces() 返回 Enumeration<NetworkInterface>
     */
    public static ContainerTypeEnum getContainerType(JavaField jf, VariableTypeEnum type) {
        if (jf.getType().isArray()) {
            return ContainerTypeEnum.ARRAY;
        }
        if (type != VariableTypeEnum.REFERENCE) {
            return ContainerTypeEnum.NOT;
        }
        if (jf.getType().isA("java.util.Collection")) {
            return ContainerTypeEnum.COLLECTION;
        }
        if (jf.getType().isA("java.util.Map")) {
            return ContainerTypeEnum.MAP;
        }
        if (jf.getType().isA("java.util.Enumeration") ||
                jf.getType().isA("java.util.Iterator")) {
            return ContainerTypeEnum.CUSTOM;
        }
        return ContainerTypeEnum.NOT;
    }

    /**
     * 获取变量具体类型
     */
    public static Object getOriginClass(VariableTypeEnum type, JavaField jf) throws ParseException {
        ClassEntity declaringClass = ClassParser.createClassEntity(jf.getDeclaringClass());
        if (type == VariableTypeEnum.TYPE_PARAMETER) {
            for (TypeParameter tp : declaringClass.getTypeParameters()) {
                if (tp.getNameAsString().equals(jf.getType().toString())) {
                    return tp;
                }
            }
        } else if (type == VariableTypeEnum.PRIMITIVE) {
            return jf.getType().toString();
        } else if (type == VariableTypeEnum.REFERENCE) {
            return jf.getType();
        }
        return null;
    }

    /**
     * 获取变量分类
     */
    public static VariableTypeEnum getVariableType(JavaField jf) {
        if (isGeneric(jf)) {
            return VariableTypeEnum.TYPE_PARAMETER;
        } else if (jf.getType().isPrimitive()) {
            return VariableTypeEnum.PRIMITIVE;
        } else {
            return VariableTypeEnum.REFERENCE;
        }
    }

    /**
     * 获取访问修饰符
     */
    public static AccessModifierEnum getAccessModifier(JavaField jf) {
        if (jf.isPublic()) {
            return AccessModifierEnum.PUBLIC;
        } else if (jf.isPrivate()) {
            return AccessModifierEnum.PRIVATE;
        } else if (jf.isProtected()) {
            return AccessModifierEnum.PROTECTED;
        } else {
            return AccessModifierEnum.DEFAULT;
        }
    }

    /**
     * 判断是类型变量，与类型变量声明列表匹配
     */
    public static boolean isGeneric(JavaField jf) {
        for (JavaType jt : jf.getDeclaringClass().getTypeParameters()) {
            if (jf.getType().equals(jt)) {
                return true;
            }
        }
        return false;
    }
}
